{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Anaconda\\lib\\site-packages\\h5py\\__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import tensorflow as tf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "plt.rcParams['font.sans-serif'] = 'SimHei' ##设置字体为SimHei显示中文\n",
    "plt.rcParams['axes.unicode_minus'] = False ##设置正常显示符号"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>时间</th>\n",
       "      <th>开</th>\n",
       "      <th>高</th>\n",
       "      <th>低</th>\n",
       "      <th>收</th>\n",
       "      <th>量</th>\n",
       "      <th>额</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1999-01-01</td>\n",
       "      <td>0.103</td>\n",
       "      <td>0.103</td>\n",
       "      <td>0.103</td>\n",
       "      <td>0.103</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1999-01-04</td>\n",
       "      <td>0.102</td>\n",
       "      <td>0.102</td>\n",
       "      <td>0.102</td>\n",
       "      <td>0.102</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1999-01-05</td>\n",
       "      <td>0.103</td>\n",
       "      <td>0.103</td>\n",
       "      <td>0.103</td>\n",
       "      <td>0.103</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1999-01-06</td>\n",
       "      <td>0.104</td>\n",
       "      <td>0.104</td>\n",
       "      <td>0.104</td>\n",
       "      <td>0.104</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1999-01-07</td>\n",
       "      <td>0.103</td>\n",
       "      <td>0.103</td>\n",
       "      <td>0.103</td>\n",
       "      <td>0.103</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          时间      开      高      低      收  量  额\n",
       "0 1999-01-01  0.103  0.103  0.103  0.103  0  0\n",
       "1 1999-01-04  0.102  0.102  0.102  0.102  0  0\n",
       "2 1999-01-05  0.103  0.103  0.103  0.103  0  0\n",
       "3 1999-01-06  0.104  0.104  0.104  0.104  0  0\n",
       "4 1999-01-07  0.103  0.103  0.103  0.103  0  0"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "## 导入数据\n",
    "df = pd.read_csv('./人民币-欧元.csv',encoding='gbk',engine='python')\n",
    "df['时间'] = pd.to_datetime(df['时间'],format='%Y/%m/%d')\n",
    "df = df.sort_values(by='时间')\n",
    "df.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 定义常量\n",
    "rnn_unit = 10  # hidden layer units\n",
    "input_size = 4\n",
    "output_size = 1\n",
    "lr = 0.0006  # 学习率\n",
    "# ——————————————————导入数据——————————————————————\n",
    "data = df.iloc[:, 1:5].values  # 取第3-10列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 获取训练集\n",
    "def get_train_data(batch_size=60, time_step=30, train_begin=0, train_end=len(data)-101):\n",
    "    batch_index = []\n",
    "    data_train = data[train_begin:train_end]\n",
    "    normalized_train_data = (data_train - np.mean(data_train, axis=0)) / np.std(data_train, axis=0)  # 标准化\n",
    "    train_x, train_y = [], []  # 训练集\n",
    "    for i in range(len(normalized_train_data) - time_step):\n",
    "        if i % batch_size == 0:\n",
    "            batch_index.append(i)\n",
    "        x = normalized_train_data[i:i + time_step, :4]\n",
    "        y = normalized_train_data[i:i + time_step, 4, np.newaxis]\n",
    "        train_x.append(x.tolist())\n",
    "        train_y.append(y.tolist())\n",
    "    batch_index.append((len(normalized_train_data) - time_step))\n",
    "    return batch_index, train_x, train_y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 获取测试集\n",
    "def get_test_data(time_step=30, test_begin=len(data)-101):\n",
    "    data_test = data[test_begin:]\n",
    "    mean = np.mean(data_test, axis=0)\n",
    "    std = np.std(data_test, axis=0)\n",
    "    normalized_test_data = (data_test - mean) / std  # 标准化\n",
    "    size = (len(normalized_test_data) + time_step - 1) // time_step  # 有size个sample\n",
    "    test_x, test_y = [], []\n",
    "    for i in range(size - 1):\n",
    "        x = normalized_test_data[i * time_step:(i + 1) * time_step, :4]\n",
    "        y = normalized_test_data[i * time_step:(i + 1) * time_step, 4]\n",
    "        test_x.append(x.tolist())\n",
    "        test_y.extend(y)\n",
    "    test_x.append((normalized_test_data[(i + 1) * time_step:, :4]).tolist())\n",
    "    test_y.extend((normalized_test_data[(i + 1) * time_step:, 4]).tolist())\n",
    "    return mean, std, test_x, test_y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From D:\\Anaconda\\lib\\site-packages\\tensorflow\\python\\framework\\op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Colocations handled automatically by placer.\n"
     ]
    }
   ],
   "source": [
    "# ——————————————————定义神经网络变量——————————————————\n",
    "# 输入层、输出层权重、偏置\n",
    "\n",
    "weights = {\n",
    "    'in': tf.Variable(tf.random_normal([input_size, rnn_unit])),\n",
    "    'out': tf.Variable(tf.random_normal([rnn_unit, 1]))\n",
    "}\n",
    "biases = {\n",
    "    'in': tf.Variable(tf.constant(0.1, shape=[rnn_unit, ])),\n",
    "    'out': tf.Variable(tf.constant(0.1, shape=[1, ]))\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ——————————————————定义神经网络变量——————————————————\n",
    "def lstm(X):\n",
    "    batch_size = tf.shape(X)[0]\n",
    "    time_step = tf.shape(X)[1]\n",
    "    w_in = weights['in']\n",
    "    b_in = biases['in']\n",
    "    input = tf.reshape(X, [-1, input_size])  # 需要将tensor转成2维进行计算，计算后的结果作为隐藏层的输入\n",
    "    input_rnn = tf.matmul(input, w_in) + b_in\n",
    "    input_rnn = tf.reshape(input_rnn, [-1, time_step, rnn_unit])  # 将tensor转成3维，作为lstm cell的输入\n",
    "    cell = tf.nn.rnn_cell.BasicLSTMCell(rnn_unit)\n",
    "    init_state = cell.zero_state(batch_size, dtype=tf.float32)\n",
    "    output_rnn, final_states = tf.nn.dynamic_rnn(cell, input_rnn, initial_state=init_state,\n",
    "                                                 dtype=tf.float32)  # output_rnn是记录lstm每个输出节点的结果，final_states是最后一个cell的结果\n",
    "    output = tf.reshape(output_rnn, [-1, rnn_unit])  # 作为输出层的输入\n",
    "    w_out = weights['out']\n",
    "    b_out = biases['out']\n",
    "    pred = tf.matmul(output, w_out) + b_out\n",
    "    return pred, final_states"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ——————————————————训练模型——————————————————\n",
    "def train_lstm(batch_size=80, time_step=30, train_begin=0, train_end=len(data)-101):\n",
    "    X = tf.placeholder(tf.float32, shape=[None, time_step, input_size])\n",
    "    Y = tf.placeholder(tf.float32, shape=[None, time_step, output_size])\n",
    "    batch_index, train_x, train_y = get_train_data(batch_size, time_step, train_begin, train_end)\n",
    "    pred, _ = lstm(X)\n",
    "    # 损失函数\n",
    "    loss = tf.reduce_mean(tf.square(tf.reshape(pred, [-1]) - tf.reshape(Y, [-1])))\n",
    "    train_op = tf.train.AdamOptimizer(lr).minimize(loss)\n",
    "    saver = tf.train.Saver(tf.global_variables(), max_to_keep=30)\n",
    "    module_file = tf.train.latest_checkpoint()\n",
    "    with tf.Session() as sess:\n",
    "        # sess.run(tf.global_variables_initializer())\n",
    "        saver.restore(sess, module_file)\n",
    "        # 重复训练10000次\n",
    "        for i in range(2000):\n",
    "            for step in range(len(batch_index) - 1):\n",
    "                _, loss_ = sess.run([train_op, loss], feed_dict={X: train_x[batch_index[step]:batch_index[step + 1]],\n",
    "                                                                 Y: train_y[batch_index[step]:batch_index[step + 1]]})\n",
    "            print(i, loss_)\n",
    "            if i % 200 == 0:\n",
    "                print(\"保存模型：\", saver.save(sess, 'stock2.model', global_step=i))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "# ————————————————预测模型————————————————————\n",
    "def prediction(time_step=30):\n",
    "    X = tf.placeholder(tf.float32, shape=[None, time_step, input_size])\n",
    "    # Y=tf.placeholder(tf.float32, shape=[None,time_step,output_size])\n",
    "    mean, std, test_x, test_y = get_test_data(time_step)\n",
    "    pred, _ = lstm(X)\n",
    "    saver = tf.train.Saver(tf.global_variables())\n",
    "    with tf.Session() as sess:\n",
    "        # 参数恢复\n",
    "        module_file = tf.train.latest_checkpoint()\n",
    "        saver.restore(sess, module_file)\n",
    "        test_predict = []\n",
    "        for step in range(len(test_x) - 1):\n",
    "            prob = sess.run(pred, feed_dict={X: [test_x[step]]})\n",
    "            predict = prob.reshape((-1))\n",
    "            test_predict.extend(predict)\n",
    "        test_y = np.array(test_y) * std[4] + mean[4]\n",
    "        test_predict = np.array(test_predict) * std[4] + mean[4]\n",
    "        acc = np.average(np.abs(test_predict - test_y[:len(test_predict)]) / test_y[:len(test_predict)])  # 偏差\n",
    "        print(acc)\n",
    "        # 以折线图表示结果\n",
    "        plt.figure()\n",
    "        plt.plot(list(range(len(test_predict))), test_predict, color='b')\n",
    "        plt.plot(list(range(len(test_y))), test_y, color='r')\n",
    "        plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "ename": "IndexError",
     "evalue": "index 4 is out of bounds for axis 1 with size 4",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mIndexError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-11-f1a4178fbe2c>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;32mwith\u001b[0m \u001b[0mtf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvariable_scope\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'train'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m     \u001b[0mtrain_lstm\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      3\u001b[0m \u001b[1;32mwith\u001b[0m \u001b[0mtf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvariable_scope\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'train'\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mreuse\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      4\u001b[0m     \u001b[0mprediction\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m<ipython-input-9-bd60996b7f23>\u001b[0m in \u001b[0;36mtrain_lstm\u001b[1;34m(batch_size, time_step, train_begin, train_end)\u001b[0m\n\u001b[0;32m      3\u001b[0m     \u001b[0mX\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mplaceholder\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfloat32\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mshape\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtime_step\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0minput_size\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      4\u001b[0m     \u001b[0mY\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mtf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mplaceholder\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtf\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfloat32\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mshape\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;32mNone\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtime_step\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0moutput_size\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 5\u001b[1;33m     \u001b[0mbatch_index\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrain_x\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrain_y\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mget_train_data\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mbatch_size\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtime_step\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrain_begin\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtrain_end\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      6\u001b[0m     \u001b[0mpred\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0m_\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mlstm\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mX\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      7\u001b[0m     \u001b[1;31m# 损失函数\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m<ipython-input-5-fe0f7aa7e747>\u001b[0m in \u001b[0;36mget_train_data\u001b[1;34m(batch_size, time_step, train_begin, train_end)\u001b[0m\n\u001b[0;32m      9\u001b[0m             \u001b[0mbatch_index\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     10\u001b[0m         \u001b[0mx\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnormalized_train_data\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m:\u001b[0m\u001b[0mi\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mtime_step\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m:\u001b[0m\u001b[1;36m4\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 11\u001b[1;33m         \u001b[0my\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnormalized_train_data\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m:\u001b[0m\u001b[0mi\u001b[0m \u001b[1;33m+\u001b[0m \u001b[0mtime_step\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m4\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mnewaxis\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     12\u001b[0m         \u001b[0mtrain_x\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtolist\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     13\u001b[0m         \u001b[0mtrain_y\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtolist\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mIndexError\u001b[0m: index 4 is out of bounds for axis 1 with size 4"
     ]
    }
   ],
   "source": [
    "with tf.variable_scope('train'):\n",
    "    train_lstm()\n",
    "with tf.variable_scope('train',reuse=True):\n",
    "    prediction()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
